#include "actor.hpp"

#include "image.hpp"
#include "video.hpp"
#include "audio.hpp"

Actor::Actor()
{
	Reset();
}

Actor::~Actor()
{
}

void Actor::Reset()
{
	hp = -1;

	body = Box2f(Vec2f(0, 0), Vec2f(0, 0));
	pos = Vec2f(0, 0);
	vel = Vec2f(0, 0);
	dir = 1;

	stghit = Vec2f(FLT_MAX, FLT_MAX);

	red = grn = blu = alpha = 1;
	img = 0;
	frame = 0;
	snd = 0;
	chan = -1;
	if (grid.TileCt())
		grid.Resize(0, 0);
}

Vec2f Actor::OutVel(float upfrac)
{
	Vec2f outvel (0, 0);

	for (int ax = X; ax < AXISCT; ++ax)
		if (!StgHitting(ax) || stghit[ax] == 0)
			outvel[ax] = vel[ax] * upfrac;

	return outvel;
}

Vec2f Actor::OutPos(float upfrac)
{
	return pos + OutVel(upfrac);
}

#include "camera.hpp"

Vec2f Actor::LookPos(float upfrac)
{
	Vec2f lookpos (OutPos(upfrac) - Cam.HSize());
	return lookpos;
}

void Actor::LookAt(float upfrac)
{
	Vec2f lookpos(LookPos(upfrac));
	Cam.Vel(0, 0);
	Cam.Pos(lookpos.x, lookpos.y);
	Cam.Out(upfrac);
}

void Actor::Out(float upfrac)
{
	Vec2f outpos (OutPos(upfrac));
	
	if (snd)
	{
		Aud.Pos(outpos.x,// + body.AxHalf(X),
				outpos.y);// + body.AxHalf(Y));
		Aud.Loop(0);
		chan = Aud.SoundPlay(*snd, chan);
		snd = NULL;
	}

	if (!alpha)
		return;

	//if (img && !grid.TileCt())
	//{
	//	outpos += body.off;
	//	outpos.x += 0.5f * (body.size.x - img->TileWidth());
	//	outpos.y += 0.5f * (body.size.y - img->TileHeight());
	//}

	Vid.Pos(outpos.x, outpos.y);
	Vid.Pri(0);

	Vid.Flip(dir < 0, false);
	Vid.Color(red, grn, blu, alpha);

	if (img && img->Opened())
	{
		if (grid.TileCt())
			Vid.TilesDraw(*img, grid.Data(), 
					grid.Cols(), grid.Rows());
		else
			Vid.SpriteDraw(*img, (int)frame % img->TileCt());
	}
	//else
	{
		outpos = (OutPos(upfrac));
		Vid.Pos(outpos.x + body.off.x, outpos.y + body.off.y);
		Vid.Color(0, grn, 0, alpha);
		Vid.BoxDraw(body.size.x, body.size.y);

		Vid.Pos(outpos.x - .25f, outpos.y - .25f);
		Vid.Color(red, 0, 0, alpha);
		Vid.BoxDraw(.5f, .5f);
	}
}

bool Actor::Gone()
{
	return pos.DistSq(Cam.Center()) > 32*32;
}

ActList::ActList()
{
}

ActList::~ActList()
{
}

void ActList::Add(Actor *a)
{
	if (a && a->Exists())
		actors.push_back(a);
}

void ActList::Update()
{
	for (Iter it = actors.begin(); it != actors.end(); ++it)
	{
		Actor *a = *it;
		a->Update();
	}
}

void ActList::Out(float upfrac)
{
	for (Iter it = actors.begin(); it != actors.end(); ++it)
	{
		Actor *a = *it;
		a->Out(upfrac);
	}
}

void ActList::Bury()
{
	for (Iter it = actors.begin(); it != actors.end(); )
	{
		Actor *a = *it;
		if (!a->Exists())
			it = actors.erase(it);
		else
			++it;
	}
}

void ActList::Clear()
{
	for (Iter it = actors.begin(); 
		it != actors.end(); 
		it = actors.erase(it))
	{
		(*it)->Reset();
	}
}

ActList AllActs;
